﻿using Aliyun.OSS;
using BP.DA;
using BP.Difference;
using BP.Port;
using BP.Sys;
using BP.Tools;
using BP.Web;
using Microsoft.AspNetCore.Server.IIS.Core;
using NetTaste;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.OpenXmlFormats.Dml;
using NPOI.SS.Formula.Udf;
using Org.BouncyCastle.Crypto.Tls;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Security.Policy;
using System.Text;
using Ubiety.Dns.Core;

namespace BP.En
{
    /// <summary>
    /// 可以被重写的类 
    /// </summary>
    public class OverrideFile
    {
        public static string GetMd5Hash(string input)
        {
            return DBAccess.GenerMD5(input);
        }
        /// <summary>
        /// 登录方法
        /// </summary>
        /// <param name="dbsrcNo">数据源</param>
        /// <returns>token</returns>
        /// <exception cref="Exception"></exception>
        public static string Data_WebApi_Login(SFDBSrc dbSrc)
        {
            //1. 先从cokes取.
            string token = BP.Web.WebUser.GetSessionByKey(dbSrc.No, null);

            //2. 如果没有token就生成token.
            if (DataType.IsNullOrEmpty(token) == false)
                return token;

            #region 本机数据源获取token.
            //3. 获取token的方法.
            if (dbSrc.No.Equals("localWebApi") == true)
            {
                string url = dbSrc.ConnString + "/";
                string data = BP.Tools.PubGlo.HttpPostConnect(url, null, "GET", true, null);
                dynamic jsonFS = JsonConvert.DeserializeObject(data);
                if (jsonFS.code != 200)
                    throw new Exception("err@获取token出现错误.");

                token = WebUser.Token;
                BP.Web.WebUser.SetSessionByKey(dbSrc.No, token);
                return token;
            }
            #endregion 本机数据源获取token.

            #region 方策：获取token.
            if (dbSrc.No.Equals("fsjma.cn") == true)
            {
                string passWord = DBAccess.RunSQLReturnStringIsNull("SELECT Pass FROM Port_Emp WHERE No='" + WebUser.No + "'", null);
                if (passWord == null)
                    throw new Exception("err@用户不存在或者没有密码.");

                string url = "http://comms.fsjma.cn:8089/CommonAppServer/Account/Login?commstest=XCDemo";
                string userNo = "fccgy"; // WebUser.No;
                string userName = "方策-陈刚毅"; // WebUser.Name;
                passWord = "chan9808";

                string md5 = userNo + GetMd5Hash(userNo.ToLower()) + GetMd5Hash(passWord);
                // fccgy
                //fccgy + md5(fccgy) + md5(chan9808)
                //username + MD5(username).toString() + MD5(password).toString()
                // string val = userNo + GetMd5Hash(userNo) + GetMd5Hash(passWord)+userName;
                //  string bodyData = "{'AppName': 'Web','UniqueID':'123456','UserType': 'comms','UserID': '" + WebUser.No + "','Pwd': '" + val + "'｝";
                string bodyData = "{'AppName': 'Web','UniqueID':'123456','UserType': 'comms','UserID': '" + userNo + "','Pwd':'" + md5 + "'｝";
                string header = "{md5:'" + GetMd5Hash(bodyData) + "'}";

                header = @"{md5:'7420a13941120697768cad813578c2ce'}";
                bodyData = @"{ 'UserType': 'comms','UserID': 'fccgy','Pwd': 'fccgy0fedaa6cb0d2b06b6065096056c0aea36671d7345e7ff3ac0b6e874d971394ed','UniqueID': 'fATq6gFQK7A6n7Zx0000796534427765','AppName':'Web'}";
                // bodyData = "{ UserType: 'comms', UserID: 'fccgy',Pwd :'fccgy0fedaa6cb0d2b06b6065096056c0aea36671d7345e7ff3ac0b6e874d971394ed', UniqueID: 'fATq6gFQK7A6n7Zx0000796534427765',AppName:'Web'}";
                //通过下面的方法获取token.
                string data = BP.Tools.PubGlo.HttpPostConnect(url, bodyData, "POST", true, header);
                dynamic jsonFS = JsonConvert.DeserializeObject(data);
                if (jsonFS != null)
                {
                    if (jsonFS.code != 0)
                        throw new Exception("err@密码或者用户名错误，数据:" + data);
                    BP.Web.WebUser.SetSessionByKey(dbSrc.No, jsonFS.accessToken);
                    return jsonFS.accessToken;
                }
                throw new Exception("err@获取token错误:" + data + " url:" + url + ", bodyData=" + bodyData + "  header=" + header);
            }
            #endregion 方策：获取token.

            throw new Exception("err@没有判断的数据源[" + dbSrc.No + "]获取token的方法.");
        }
        /// <summary>
        /// 处理别名参数
        /// </summary>
        /// <param name="ht"></param>
        /// <param name="paramAlia"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static Hashtable DealHT_ParamAlia(Hashtable ht, string paramAlia)
        {
            try
            {
                if (ht == null)
                    ht = new Hashtable();
                // ht 里面如果有别名，就把它修正为参数.
                if (DataType.IsNullOrEmpty(paramAlia) == true)
                    return ht;
                string err = "";
                paramAlia = paramAlia.Replace(";", "@");

                if (paramAlia.Contains("=") == false)
                    throw new Exception("参数别名不符合规则:" + paramAlia);

                if (paramAlia.Contains("@") == false)
                    paramAlia = "@" + paramAlia;

                AtPara paraAlia = new AtPara(paramAlia);
                foreach (string key in paraAlia.HisHT.Keys)
                {
                    string aliaKeys = "," + paraAlia.HisHT[key].ToString() + ",";

                    //检查传递过来的参数里是否有这样的字段,如果有就复制这个值，按照实体参数名增加进去.
                    Hashtable tempHt = new Hashtable(); //直接插入容易出错.

                    foreach (string paraKey in ht.Keys)
                    {
                        if (aliaKeys.Contains("," + paraKey + ",") == false)
                            continue;

                        if (ht.ContainsKey(key) == true)
                            continue; //如果包含了参数的值.

                        if (tempHt.ContainsKey(key) == false)
                            tempHt.Add(key, ht[paraKey]); //复制值，并插入里面去.
                    }

                    //增加补充到ht里面.
                    foreach (string tempKey in tempHt.Keys)
                    {
                        if (ht.ContainsKey(tempKey) == true)
                            continue; //如果包含了参数的值.
                        ht.Add(tempKey, tempHt[tempKey]); //复制值，并插入里面去.
                    }
                }
                return ht;
            }
            catch (Exception ex)
            {
                throw new Exception("err@处理参数别名期间出现错误:" + ex.Message);
            }
        }
        /// <summary>
        /// 获得webApi数据: 这个方法需要重写,返回的是结果数据
        ///更多信息请参考：https://docs.qq.com/doc/DRG52QmlyeG1kSUJE
        /// </summary>
        /// <param name="ht">参数KeyVal的模式</param>
        /// <param name="requestMethod">POST/GET</param>
        /// <param name="dbSrcNo">数据源编号</param>
        /// <param name="apiUrl">执行部分比如: /Ports</param>
        /// <param name="bodyData">对于post有效： ｛key1:xxx,key2:yyy｝</param>
        /// <param name="headerData">对于post有效： ｛key1:xxx,key2:yyy｝</param>
        /// <param name="paramAlia">别名格式：@Tel=DH,DianHua@Email=YouJian,YJ,参数名有多种表达方式，在ht里获取值。</param>
        /// <returns>返回的数据格式：{ code:'000', msg:'xxx',data:'yyyy' } </returns>
        public static ResultObj Data_WebApi(Hashtable ht, string requestMethod, string dbSrcNo, string apiUrl, string paramAlia = "", string bodyData = "", string headerData = "")
        {
            ht = DealHT_ParamAlia(ht, paramAlia);
            //先设置为空.
            SFDBSrc mysrc = new SFDBSrc(dbSrcNo);
            apiUrl = mysrc.ConnString + "/" + apiUrl;

            #region 处理变量 - 替换已经有的参数。
            if (ht == null) ht = new Hashtable();
            bodyData = bodyData.Replace("~~", "\"");
            bodyData = bodyData.Replace("~", "\'");
            bodyData = DealContext(bodyData, ht);

            headerData = headerData.Replace("~~", "\"");
            headerData = headerData.Replace("~", "\'");
            headerData = DealContext(headerData, ht);
            //处理url.
            apiUrl = DealUrl(apiUrl, ht);
            #endregion 处理变量. -替换已经有的参数

            #region 处理变量 - 处理数据源固定参数. 
            if (headerData.Contains("@") || bodyData.Contains("@") || apiUrl.Contains("@"))
            {
                //获得参数.
                SFApiParas paras = new SFApiParas();
                paras.Retrieve("DBSrcNo", dbSrcNo);
                foreach (SFApiPara para in paras)
                {
                    // ApiParaModel @0=常量@1=业务单元@2=SQL表达式
                    if (para.ApiParaModel == 0)
                    {
                        ht.Add(para.AttrKey, para.ExpDoc);
                        continue;
                    }
                    //如果是业务单元: ApiParaModel= @0=常量@1=业务单元@2=SQL表达式
                    if (para.ApiParaModel == 1)
                    {
                        // 是存储到cookes里面的
                        if (para.ApiParaStore == 0)
                        {
                            string val = WebUser.GetSessionByKey(para.AttrKey + "_" + dbSrcNo, null);
                            if (val != null)
                            {
                                ht.Add(para.AttrKey, val);
                                continue;
                            }
                        }
                        //获取值.
                        BuessUnitBase enBuesss = BP.Sys.Base.Glo.GetBuessUnitEntityByEnName(para.ExpDoc);
                        if (enBuesss == null)
                            throw new Exception("err@没有实例化业务单元实体:[" + para.ExpDoc + "]请检查，该类是否移除? ");
                        enBuesss.HisSFDSrc = mysrc;
                        enBuesss.BodyDoc = bodyData;
                        enBuesss.HeardDoc = headerData;
                        string val2 = enBuesss.DoIt() as string;
                        if (para.ApiParaStore == 0)
                            WebUser.SetSessionByKey(para.AttrKey + "_" + dbSrcNo, val2);
                        ht.Add(para.AttrKey, val2);
                        continue;
                    }

                    //如果是SQL表达式。
                    if (para.ApiParaModel == 2)
                    {
                        // 是存储到cookes里面的
                        if (para.ApiParaStore == 0)
                        {
                            string val = WebUser.GetSessionByKey(para.AttrKey + "_" + dbSrcNo, null);
                            if (val != null)
                            {
                                ht.Add(para.AttrKey, val);
                                continue;
                            }
                        }
                        string sql = para.ExpDoc;
                        sql = Difference.Glo.DealExp(sql, ht);
                        string val2 = DBAccess.RunSQLReturnStringIsNull(sql, null);
                        if (val2 == null)
                            throw new Exception("err@获取系统参数期间出现错误:SQL表达式:" + sql + ",没有获得数据.");

                        if (para.ApiParaStore == 0)
                            WebUser.SetSessionByKey(para.AttrKey + "_" + dbSrcNo, val2);
                        ht.Add(para.AttrKey, val2);
                        continue;
                    }
                }
                bodyData = DealContext(bodyData, ht);
                headerData = DealContext(headerData, ht);
                apiUrl = DealContext(apiUrl, ht);
            }
            if (apiUrl.Contains("@") == true || bodyData.Contains("@") || headerData.Contains("@") == true)
            {
                ResultObj obj = new ResultObj();
                obj.code = 500;
                obj.message = "配置或者参数错误";
                obj.data = "如下参数里的变量没有替换: apiURL=[" + apiUrl + "],bodyData=[" + bodyData + "],headerData=[" + headerData + "]";
                return obj;
            }
            #endregion 处理变量 - 处理数据源固定参数.

            //调用通用的处理模式,获取原始数据.
            string data = null;
            try
            {
                data = Data_WebApi_Gener(requestMethod, apiUrl, bodyData, headerData);

                if (data.Contains("err@") == true)
                {
                    ResultObj obj = new ResultObj();
                    obj.message = "获取数据失败";
                    obj.code = 500;
                    if (data.Contains("404") == true)
                    {
                        obj.code = 404;
                        obj.message = "链接错误";
                    }
                    obj.data = "错误内容:[" + data + "]URL:[" + apiUrl + "], 参数bodyData:" + bodyData + " 参数headerData:" + headerData;
                    return obj;
                }

                if (DataType.IsNullOrEmpty(data) == true)
                    throw new Exception("原始数据为空");
            }
            catch (Exception ex)
            {
                ResultObj obj = new ResultObj();
                obj.code = 500;
                obj.message = "获取数据失败";

                string msg = "";
                if (mysrc.No.Equals("localWebApi") == true)
                {
                    string host = mysrc.ConnString;
                    msg += "当前webApi是localWebApi请检查全局配置:app.config或jflow.properties, HostUrl配置项的值=[" + host + "]是否正确?";
                }

                obj.data = msg + "错误内容:[" + ex.Message + "]原始数据:[" + data + "]URL:[" + apiUrl + "], 参数bodyData:" + bodyData + " 参数headerData:" + headerData;
                return obj;
            }


            try
            {
                dynamic json = JsonConvert.DeserializeObject(data);
            }
            catch (Exception ex)
            {
                // 使用正确的编码（如GB2312）来解码
                Encoding gb2312 = Encoding.GetEncoding("GB2312");
                //    string correctString = gb2312.GetString(data);

            }


            ////如果不需要格式转换，按照ccbpm的标准开发的.
            //if (mysrc.No== "Weather")
            //{
            //    dynamic json = JsonConvert.DeserializeObject(data);
            //    ResultObj obj = new ResultObj();
            //    obj.code = json.code; // 200=执行成功, 404=配置错误，500=执行错误.
            //    obj.message = json.fxLink;
            //    obj.data = new JArray(json.daily).ToString();
            //    return obj;
            //}
            if (mysrc.WebApiResultModel == 0)
            {
                try
                {

                    dynamic json = JsonConvert.DeserializeObject(data);
                    ResultObj obj = new ResultObj();
                    obj.code = json.code; // 200=执行成功, 404=配置错误，500=执行错误.
                    obj.message = json.message;
                    obj.data = json.data;
                    return obj;
                }
                catch (Exception ex)
                {
                    ResultObj obj = new ResultObj();
                    obj.code = 500;
                    obj.message = "返回数据格式错误.";
                    obj.data = "错误内容:" + ex.Message + " 原始数据:" + data;
                    return obj;
                }
            }

            //如果需要自定义格式转换.
            if (mysrc.WebApiResultModel == 1)
            {
                BuessUnitBase enBuesss = BP.Sys.Base.Glo.GetBuessUnitEntityByEnName(mysrc.WebApiResultObjEnName);
                enBuesss.WebApiDBSrcUrl = apiUrl; //访问的Url.
                enBuesss.HisSFDSrc = mysrc;  //数据源编号》
                enBuesss.BodyDoc = bodyData; //body 参数。
                enBuesss.HeardDoc = headerData; // 参数
                enBuesss.resultData = data; //远程返回的结果.
                enBuesss.DoIt(); //执行.
                if (enBuesss.resultObj == null)
                    throw new Exception("err@数据获取成功,对结果进行结果标准转换错误:使用方法[" + mysrc.WebApiResultObjEnName + "],数据结果:" + data);
                return enBuesss.resultObj;
            }

            throw new Exception("err@没有判断的格式转换模式：" + mysrc.WebApiResultModel);
        }

        public static string Data_WebApi_Gener(string requestMethod, string apiUrl, string bodyData = "", string headerData = "")
        {
            try
            {
                #region  GET 解析路径变量 /{xxx}/{yyy} ? xxx=xxx
                if (requestMethod.ToUpper().Equals("GET") == true)
                {
                     return BP.Tools.PubGlo.HttpGet(apiUrl);
                }
                #endregion GET 解析路径变量 /{xxx}/{yyy} ? xxx=xxx

                return BP.Tools.PubGlo.HttpPostConnect(apiUrl, bodyData, "POST", true, headerData);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }
        public static ResultObj Data_WebApi_GenerStandReturnObj(string requestMethod, string apiUrl, string bodyData = "", string headerData = "")
        {
            string data = null;
            try
            {
                data = Data_WebApi_Gener(requestMethod, apiUrl, bodyData, headerData);
                if (data.Contains("err@") == true)
                {
                    ResultObj obj = new ResultObj();
                    obj.message = "获取数据失败";
                    obj.code = 500;
                    if (data.Contains("404") == true)
                    {
                        obj.code = 404;
                        obj.message = "链接错误";
                    }
                    obj.data = "错误内容:[" + data + "]URL:[" + apiUrl + "], 参数bodyData:" + bodyData + " 参数headerData:" + headerData;
                    return obj;
                }
                if (DataType.IsNullOrEmpty(data) == true)
                    throw new Exception("原始数据为空");
            }
            catch (Exception ex)
            {
                ResultObj obj = new ResultObj();
                obj.code = 500;
                obj.message = "获取数据失败";
                obj.data = "错误内容:[" + ex.Message + "]原始数据:[" + data + "]URL:[" + apiUrl + "], 参数bodyData:" + bodyData + " 参数headerData:" + headerData;
                return obj;
            }

            //转化为标准格式.
            try
            {
                dynamic json = JsonConvert.DeserializeObject(data);
                ResultObj obj = new ResultObj();
                obj.code = json.code; // 200=执行成功, 404=配置错误，500=执行错误.
                obj.message = json.message;
                obj.data = json.data;
                return obj;
            }
            catch (Exception ex)
            {
                ResultObj obj = new ResultObj();
                obj.code = 500;
                obj.message = "返回数据格式错误.";
                obj.data = "错误内容:" + ex.Message + " 原始数据:" + data;
                return obj;
            }


        }
        private static string DealUrl(string apiUrl, Hashtable ht)
        {
            apiUrl = apiUrl.Replace("@WebUser.No", WebUser.No);
            apiUrl = apiUrl.Replace("@WebUser.Name", WebUser.Name);
            apiUrl = apiUrl.Replace("@WebUser.DeptNo", WebUser.DeptNo);
            apiUrl = apiUrl.Replace("@WebUser.DeptName", WebUser.DeptName);
            apiUrl = apiUrl.Replace("@WebUser.OrgNo", WebUser.OrgNo);
            apiUrl = apiUrl.Replace("@WebUser.Token", WebUser.Token);

            if (apiUrl.Contains("{") == true)
            {
                foreach (string key in ht.Keys)
                {
                    apiUrl = apiUrl.Replace("{" + key + "}", ht[key].ToString());
                }
            }
            else
            {
                foreach (string key in ht.Keys)
                {
                    apiUrl = apiUrl.Replace("@" + key, ht[key].ToString());
                }
            }
            apiUrl = apiUrl.Replace("//", "/");
            apiUrl = apiUrl.Replace("//", "/");
            apiUrl = apiUrl.Replace(":/", "://");
            return apiUrl;
        }
        private static string DealContext(string bodyData, Hashtable ht)
        {
            if (DataType.IsNullOrEmpty(bodyData))
                bodyData = "";
            bodyData = bodyData.Replace("~~", "\"");
            bodyData = bodyData.Replace("~", "\"");
            if (DataType.IsNullOrEmpty(bodyData) == false)
            {
                bodyData = bodyData.Replace("@WebUser.No", WebUser.No);
                bodyData = bodyData.Replace("@WebUser.Name", WebUser.Name);
                bodyData = bodyData.Replace("@WebUser.DeptNo", WebUser.DeptNo);
                bodyData = bodyData.Replace("@WebUser.DeptName", WebUser.DeptName);
                bodyData = bodyData.Replace("@WebUser.OrgNo", WebUser.OrgNo);
                bodyData = bodyData.Replace("@WebUser.Token", WebUser.Token);

                foreach (string key in ht.Keys)
                {
                    bodyData = bodyData.Replace("@" + key, ht[key].ToString());
                }
            }
            return bodyData;
        }


        #region 可以重写的表单事件.
        /// <summary>
        /// 执行的事件
        /// </summary>
        /// <param name="frmID"></param>
        /// <param name="en"></param>
        public static string FrmEvent_LoadBefore(string frmID, Entity en)
        {
            return null;
        }
        /// <summary>
        /// 装载填充的事件.
        /// </summary>
        /// <param name="frmID"></param>
        /// <param name="en"></param>
        public static string FrmEvent_FrmLoadAfter(string frmID, Entity en)
        {
            return null;
        }
        /// <summary>
        /// 保存前事件
        /// </summary>
        /// <param name="frmID"></param>
        /// <param name="en"></param>
        public static string FrmEvent_SaveBefore(string frmID, Entity en)
        {
            return null;
        }
        /// <summary>
        /// 保存后事件
        /// </summary>
        /// <param name="frmID"></param>
        /// <param name="en"></param>
        public static string FrmEvent_SaveAfter(string frmID, Entity en)
        {
            return null;
        }
        public static string FrmBill_CheckStart(string frmID, Entity en)
        {
            return null;
        }
        /// <summary>
        /// 单据实体审核结束以后
        /// </summary>
        /// <param name="frmID">单据ID</param>
        /// <param name="en">实体</param>
        public static string FrmBill_CheckOver(string frmID, Entity en)
        {
            return null;
        }
        /// <summary>
        /// 单据重新审核(回滚)
        /// </summary>
        /// <param name="frmID"></param>
        /// <param name="en"></param>
        /// <returns></returns>
        public static string FrmBill_Reback(string frmID, Entity en)
        {
            return null;
        }
        /// <summary>
        /// 单据实体撤销审核
        /// </summary>
        /// <param name="frmID"></param>
        /// <param name="en"></param>
        public static string FrmBill_UnSend(string frmID, Entity en)
        {
            return null;
        }
        public static string FrmBill_OverBefore(string frmID, Entity en)
        {
            return null;
        }
        public static string FrmBill_OverAfter(string frmID, Entity en)
        {
            return null;
        }
        public static string PrintRTF_After(string workID,string frmID,DataSet ds)
        {
            return null;
        }
        public static string PrintPDF_After(string workID, string frmID, DataSet ds)
        {
            return null;
        }
        #endregion 可以重写的表单事件.
    }
}
